package com.jtcoding.chat.service.impl;

import com.jtcoding.chat.common.enums.ResultCode;
import com.jtcoding.chat.dao.chat.FriendDao;
import com.jtcoding.chat.exception.ApiException;
import com.jtcoding.chat.model.Friend;
import com.jtcoding.chat.model.FriendRequest;
import com.jtcoding.chat.model.User;
import com.jtcoding.chat.service.FriendService;
import com.jtcoding.chat.service.NettyService;
import com.jtcoding.chat.service.UserService;
import io.netty.channel.Channel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.jtcoding.chat.service.UserService.USER_NET_STATE_OFFLINE;
import static com.jtcoding.chat.service.UserService.USER_NET_STATE_ONLINE;

/**
 * @author jason.tang
 * @create 2019-01-31 17:26
 * @description
 */
@Service("friendService")
public class FriendServiceImpl implements FriendService {

    @Autowired
    private FriendDao friendDao;

    @Autowired
    private UserService userService;

    @Autowired
    private NettyService nettyService;

    @Override
    public List<User> getFriendListByUserNum(Integer userNum) {
        List<Friend> friendList = friendDao.getFriendListByUserNum(userNum);
        Integer[] friendNum = friendList.stream()
                .map(Friend::getFriendNum)
                .toArray(Integer[]::new);
        if (friendNum.length > 0) {
            List<User> userList = userService.getUserByNums(friendNum);
            for (User user : userList) {
                Channel channel = nettyService.getChannelByNum(user.getUserNum());
                if (channel == null) {
                    user.setNetState(USER_NET_STATE_OFFLINE);
                } else {
                    user.setNetState(USER_NET_STATE_ONLINE);
                }
                Friend friend = friendList.stream()
                        .filter(f -> Objects.equals(f.getFriendNum(), user.getUserNum()))
                        .findFirst()
                        .orElse(null);
                user.setRemark(friend.getRemark());
            }
            return userList;
        }
        return new ArrayList<>();
    }

    @Override
    public List<User> searchUser(String keyword) {
        return userService.searchUser(keyword);
    }

    @Transactional
    @Override
    public Boolean addFriendRequest(FriendRequest friendRequest) {
        friendRequest.setStatus(FRIEND_REQUEST_STATUS_PND);
        return friendDao.addFriendRequest(friendRequest) > 0;
    }

    @Override
    public List<User> getUserByFriendReq(Integer userNum) {
        List<FriendRequest> requestList = friendDao.getFriendRequestListByUserNum(userNum);
        Integer[] userNums = requestList.stream()
                .map(FriendRequest::getFromUserNum)
                .toArray(Integer[]::new);
        if (userNums.length == 0) {
            return new ArrayList<>();
        }
        return userService.getUserByNums(userNums);
    }

    @Transactional
    @Override
    public User acceptFriendRequest(FriendRequest friendRequest) {
        FriendRequest orignalFriendReq = friendDao.getFriendRequest(friendRequest.getFromUserNum(), friendRequest.getToUserNum());
        if (orignalFriendReq == null || !Objects.equals(orignalFriendReq.getStatus(), FRIEND_REQUEST_STATUS_PND)) {
            throw new ApiException(ResultCode.PARAM_IS_INVALID);
        }
        orignalFriendReq.setStatus(FRIEND_REQUEST_STATUS_APV);
        int rtn = friendDao.updateFriendRequest(orignalFriendReq);
        if (rtn == 0) {
            throw new ApiException("接受申请失败...");
        }
        User fromUser = userService.getUserByNum(orignalFriendReq.getFromUserNum());
        User toUser = userService.getUserByNum(orignalFriendReq.getToUserNum());

        Friend friendTo = Friend.builder().userNum(orignalFriendReq.getToUserNum())
                .friendNum(orignalFriendReq.getFromUserNum()).status(FRIEND_STATUS_NOR)
                .createDateTime(LocalDateTime.now()).remark(fromUser.getUsername()).build();
        Friend friendFrom = Friend.builder().userNum(orignalFriendReq.getFromUserNum())
                .friendNum(orignalFriendReq.getToUserNum()).status(FRIEND_STATUS_NOR)
                .createDateTime(LocalDateTime.now()).remark(toUser.getUsername()).build();
        if (orignalFriendReq.getRemark() != null && !orignalFriendReq.getRemark().isEmpty()) {
            friendTo.setRemark(orignalFriendReq.getRemark());
        }

        rtn = friendDao.addFriend(friendTo, friendFrom);
        if (rtn == 0) {
            throw new ApiException("接受申请失败...");
        }
        return fromUser;
    }

    @Transactional
    @Override
    public Boolean rejectFriendRequest(FriendRequest friendRequest) {
        FriendRequest orignalFriendReq = friendDao.getFriendRequest(friendRequest.getFromUserNum(), friendRequest.getToUserNum());
        if (orignalFriendReq == null || !Objects.equals(orignalFriendReq.getStatus(), FRIEND_REQUEST_STATUS_PND)) {
            throw new ApiException(ResultCode.PARAM_IS_INVALID);
        }
        orignalFriendReq.setStatus(FRIEND_REQUEST_STATUS_REJ);
        return friendDao.updateFriendRequest(orignalFriendReq) > 0;
    }
}